home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
CMPLTPAS
/
VECTORS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-07-01
|
11KB
|
337 lines
{--------------------------------------------------------------}
{ VECTORS }
{ }
{ Interrupt vector utility }
{ }
{ by Jeff Duntemann }
{ Turbo Pascal V5.0 }
{ Last update 7/1/88 }
{ }
{ This program allows you to inspect and change 8086 interrupt }
{ vectors, and look at the first 256 bytes pointed to by any }
{ vector. This allows the spotting of interrupt service }
{ routine "signatures" (typically the vendor's copyright }
{ notice) and also indicates when a vector points to an IRET. }
{ }
{ From: COMPLETE TURBO PASCAL 5.0 by Jeff Duntemann }
{ Scott, Foresman & Co., Inc. 1988 ISBN 0-673-38355-5 }
{--------------------------------------------------------------}
PROGRAM Vectors;
USES DOS; { For GetIntVec and SetIntVec }
{$V-} { Relaxes type checking on string lengths }
CONST
Up = True;
TYPE
String80 = String[80];
Block = ARRAY[0..255] OF Byte;
PtrPieces = ARRAY[0..3] OF Byte;
VAR
I : Integer;
VectorNumber : Integer;
Vector : Pointer;
VSeg,VOfs : Integer;
NewVector : Integer;
MemBlock : Block;
ErrorPosition : Integer;
Quit : Boolean;
Command : String80;
CommandChar : Char;
PROCEDURE StripWhite(VAR Target : String);
CONST
Whitespace : SET OF Char = [#8,#10,#12,#13,' '];
BEGIN
WHILE (Length(Target) > 0) AND (Target[1] IN Whitespace) DO
Delete(Target,1,1)
END;
PROCEDURE WriteHex(BT : Byte);
CONST
HexDigits : ARRAY[0..15] OF Char = '0123456789ABCDEF';
VAR
BZ : Byte;
BEGIN
BZ := BT AND $0F;
BT := BT SHR 4;
Write(HexDigits[BT],HexDigits[BZ])
END;
{<<<< ForceCase >>>>}
{ From: COMPLETE TURBO PASCAL by Jeff Duntemann }
{ Scott, Foresman & Co. 1986 ISBN 0-673-18600-8 }
{ Described in section 15.3 -- Last mod 2/1/86 }
FUNCTION ForceCase(Up : BOOLEAN; Target : String) : String;
CONST
Uppercase : SET OF Char = ['A'..'Z'];
Lowercase : SET OF Char = ['a'..'z'];
VAR
I : INTEGER;
BEGIN
IF Up THEN FOR I := 1 TO Length(Target) DO
IF Target[I] IN Lowercase THEN
Target[I] := UpCase(Target[I])
ELSE { NULL }
ELSE FOR I := 1 TO Length(Target) DO
IF Target[I] IN Uppercase THEN
Target[I] := Chr(Ord(Target[I])+32);
ForceCase := Target
END;
Procedure ValHex(HexString : String;
VAR Value : LongInt;
VAR ErrCode : Integer);
VAR
HexDigits : String;
Position : Integer;
PlaceValue : LongInt;
TempValue : LongInt;
I : Integer;
BEGIN
ErrCode := 0; TempValue := 0; PlaceValue := 1;
HexDigits := '0123456789ABCDEF';
StripWhite(HexString); { Get rid of leading whitespace }
IF Pos('$',HexString) = 1 THEN Delete(Hexstring,1,1);
HexString := ForceCase(Up,HexString);
IF (Length(HexString) > 8) THEN ErrCode := 9
ELSE IF (Length(HexString) < 1) THEN ErrCode := 1
ELSE
BEGIN
FOR I := Length(HexString) DOWNTO 1 DO { For each character }
BEGIN
{ The position of the character in the string is its value: }
Position := Pos(Copy(HexString,I,1),HexDigits) ;
IF Position = 0 THEN { If we find an invalid character... }
BEGIN
ErrCode := I; { ...set the error code... }
Exit { ...and exit the procedure }
END;
{ The next line calculates the value of the given digit }
{ and adds it to the cumulative value of the string: }
TempValue := TempValue + ((Position-1) * PlaceValue);
PlaceValue := PlaceValue * 16; { Move to next place }
END;
Value := TempValue
END
END;
PROCEDURE DumpBlock(XBlock : Block);
VAR
I,J,K : Integer;
Ch : Char;
BEGIN
FOR I:=0 TO 15 DO { Do a hexdump of 16 lines of 16 chars }
BEGIN
FOR J:=0 TO 15 DO { Show hex values }
BEGIN
WriteHex(Ord(XBlock[(I*16)+J]));
Write(' ')
END;
Write(' |'); { Bar to separate hex & ASCII }
FOR J:=0 TO 15 DO { Show printable chars or '.' }
BEGIN
Ch:=Chr(XBlock[(I*16)+J]);
IF ((Ord(Ch)<127) AND (Ord(Ch)>31))
THEN Write(Ch) ELSE Write('.')
END;
Writeln('|')
END;
FOR I:=0 TO 1 DO Writeln('')
END; { DumpBlock }
PROCEDURE ShowHelp;
BEGIN
Writeln;
Writeln('Press RETURN to advance to the next vector.');
Writeln;
Writeln('To display a specific vector, enter the vector number (0-255)');
Writeln('in decimal or preceded by a "$" for hex, followed by RETURN.');
Writeln;
Writeln('Valid commands are:');
Writeln;
Writeln('D : Dump the first 256 bytes pointed to by the current vector');
Writeln('E : Enter a new value (decimal or hex) for the current vector');
Writeln('H : Display this help message');
Writeln('Q : Exit VECTORS ');
Writeln('X : Exit VECTORS ');
Writeln('Z : Zero segment and offset of the current vector');
Writeln('? : Display this help message');
Writeln;
Writeln
('The indicator ">>IRET" means the vector points to an IRET instruction');
Writeln;
END;
PROCEDURE DisplayVector(VectorNumber : Integer);
VAR
Bump : Integer;
Chunks : PtrPieces;
Vector : Pointer;
Tester : ^Byte;
BEGIN
GetIntVec(VectorNumber,Vector);{ Get the vector }
Tester := Vector; { Can't dereference untyped pointer }
Chunks := PtrPieces(Vector); { Cast Vector onto Chunks }
Write(VectorNumber : 3,' $');
WriteHex(VectorNumber);
Write(' [');
WriteHex(Chunks[3]); { Write out the chunks as hex digits }
WriteHex(Chunks[2]);
Write(':');
WriteHex(Chunks[1]);
WriteHex(Chunks[0]);
Write(']');
IF Tester^ = $CF { If vector points to an IRET, say so }
THEN Write(' >>IRET ')
ELSE Write(' ');
END;
PROCEDURE DumpTargetData(VectorNumber : Integer);
VAR
Vector : Pointer;
Tester : ^Block;
BEGIN
GetIntVec(VectorNumber,Vector); { Get the vector }
Tester := Vector; { Cast the vector onto a pointer to a block }
MemBlock := Tester^; { Copy the target block into MemBlock }
IF MemBlock[0] = $CF THEN { See if the first byte is an IRET }
Writeln('Vector points to an IRET.');
DumpBlock(MemBlock) { and finally, hexdump the block. }
END;
PROCEDURE ChangeVector(VectorNumber: Integer);
VAR
Vector : Pointer;
LongTemp,TempValue : LongInt;
SegPart,OfsPart : Word;
BEGIN
GetIntVec(VectorNumber,Vector); { Get current value of vector }
LongTemp := LongInt(Vector); { Cast Pointer onto LongInt }
SegPart := LongTemp SHR 16; { Separate pointer segment from offset }
OfsPart := LongTemp AND $0000FFFF; { And keep until changed }
Write('Enter segment ');
Write('(RETURN retains current value): ');
Readln(Command);
StripWhite(Command);
IF Length(Command) > 0 THEN { If something other than RETURN was entered }
BEGIN
Val(Command,TempValue,ErrorPosition); { Evaluate as decimal }
IF ErrorPosition = 0 THEN SegPart := TempValue
ELSE { If it's not a valid decimal value, evaluate as hex: }
BEGIN
ValHex(Command,TempValue,ErrorPosition);
IF ErrorPosition = 0 THEN SegPart := TempValue
END;
Vector := Ptr(SegPart,OfsPart); { Reset the vector with any changes }
SetIntVec(VectorNumber,Vector);
END;
DisplayVector(VectorNumber); { Show it to reflect changes to segment part }
Writeln;
Write('Enter offset '); { Now get an offset }
Write('(RETURN retains current value): ');
Readln(Command);
StripWhite(Command);
IF Length(Command) > 0 THEN { If something other than RETURN was entered }
BEGIN
Val(Command,TempValue,ErrorPosition); { Evaluate as decimal }
IF ErrorPosition = 0 THEN OfsPart := TempValue
ELSE { If it's not a valid decimal value, evaluate as hex: }
BEGIN
ValHex(Command,TempValue,ErrorPosition);
IF ErrorPosition = 0 THEN OfsPart := TempValue
END
END;
Vector := Ptr(SegPart,OfsPart); { Finally, reset vector with any change: }
SetIntVec(VectorNumber,Vector);
END;
BEGIN
Quit := False;
VectorNumber := 0;
Writeln('>>VECTORS<< V2.00 by Jeff Duntemann');
Writeln(' From the book: COMPLETE TURBO PASCAL 5.0');
Writeln(' Scott, Foresman & Company, 1988');
Writeln(' ISBN 0-673-38355-5');
Writeln;
ShowHelp;
REPEAT
DisplayVector(VectorNumber); { Show the vector # & address }
Readln(Command); { Get a command from the user }
IF Length(Command) > 0 THEN { If something was typed: }
BEGIN
{ See if a number was typed; if one was, it becomes the current }
{ vector number. If an error in converting the string to a }
{ number occurs, Vectors then parses the string as a command. }
Val(Command,NewVector,ErrorPosition);
IF ErrorPosition = 0 THEN VectorNumber := NewVector
ELSE
BEGIN
StripWhite(Command); { Remove leading whitespace }
Command := ForceCase(Up,Command); { Force to upper case }
CommandChar := Command[1]; { Isolate first char. }
CASE CommandChar OF
'Q','X' : Quit := True; { Exit VECTORS }
'D' : DumpTargetData(VectorNumber); { Dump data }
'E' : ChangeVector(VectorNumber); { Enter new value }
'H' : ShowHelp;
'Z' : BEGIN { Zero the vector }
Vector := NIL; { NIL is 32 zero bits }
SetIntVec(VectorNumber,Vector);
DisplayVector(VectorNumber);
Writeln('zeroed.');
VectorNumber := (VectorNumber + 1) MOD 256
END;
'?' : ShowHelp;
END {CASE}
END
END
{ The following line increments the vector number, rolling over to 0 }
{ if the number would have exceeded 255: }
ELSE VectorNumber := (VectorNumber + 1) MOD 256
UNTIL Quit;
END.